iT邦幫忙

2023 iThome 鐵人賽

DAY 29
0
自我挑戰組

ESP32 Micropython 從入門到實用系列 第 29

29.整合WiFi網路控制

  • 分享至 

  • xImage
  •  

昨天我們在開發板上實驗,使用 MQTT 來訊息,今天我們將這樣的機制整合到我們 DIY 的變頻風扇。

我想,最方便控制變頻風扇的方式,除了紅外線遙控器外,當屬幾乎不離手的手機了。其實設計一個具有 MQTT 收發功能的 app ,應該也不是太難!而且還有圖形化的開發環境 App inventor 可以用,但這些都超出我們今天要探討的範圍。而最簡單的方式,應該是找一個現成的 MQTT client 的 app 來使用。

我們以安卓手機爲例,在 google play 中查找 "MQTT dashboard" (MQTT 儀表板):

https://ithelp.ithome.com.tw/upload/images/20231014/20140037gJy3gIR14U.png

就選 google 挑的一個來安裝吧!

在這裡可以看到這個應用軟體完整的使用說明:https://vetru-apps.github.io/mqtt-dashboard-documentation/

新增一個 Broker

執行 app 之後,我們可以按畫面最下面中間的 “+” 圖示,來增加一個 MQTT 伺服器(Broker):

Broker name: 最後顯示在軟體上面的名稱,可以是中文,注意:免費版本只能連上一個 Broker,可以加入其它的 Broker 服務器,但是必須升級爲 pro 版本才能啓用。

Address: 就填入我們測試用的 MQTT broker 地址, “test.mosquitto.org" 即可

其它欄位就使用默認值即可。

https://ithelp.ithome.com.tw/upload/images/20231014/20140037NLqT0sw4ln.jpg

底部中間有一個磁碟片圖示,按下即可儲存設定

進入到 ”風扇“ 這個 Broker 裡再做設定動作,點選底部的 ”+“ 進入設定:

我們風扇在 MQTT 訂閱的主題是”Fan/Control",因此我們在 publish 中發送的主題也需要是同一個。

由於我們要產生四個按鈕:
電源:電源開關,送出 "power" 訊息
擺頭:擺頭開關,送出 “swing” 訊息
加: 風扇風速增加一檔,送出 “up” 訊息
減: 風扇風速降低一檔,送出 “down” 訊息

https://ithelp.ithome.com.tw/upload/images/20231014/20140037gD4MqnbgeD.jpg

這樣在手機上操作,還真像是定製的應用軟體 !

我們可以用昨天在板子上訂閱 MQTT 的例子來試試,看看手機按下的按鈕發送訊息,板子能不能收到。若一切正常,接下來可以修改第27天所展示的變頻電風扇主控制程式。
https://ithelp.ithome.com.tw/upload/images/20231014/20140037WynQq5nKKX.png

可以看出,驗證 OK,開發板可以正確收到手機發送出來的訊息

我們將這些訊息轉化成控制指令,修改之前的控制程式,整合之後的程式碼如下:

from machine import Timer, Pin, SoftI2C
import FourDigitDisplay as FDD
import time
from umqtt.robust import MQTTClient
import ubinascii
import machine
from micropython import const
from ir_rx.nec import NEC_8  # NEC remote, 8 bit addresses

IR = Pin(2, Pin.IN)
buzz = Pin(7, Pin.OUT, value=0)
speed_ctl = Pin(6, Pin.OUT)
swing = Pin(3, Pin.OUT, value=0)

# IR code
ADDR = const(0)
PWR_ON = const(0x43)
SPD_UP = const(0x47)
SPD_DN = const(0x45)
SWING = const(0x46)
TMR_UP = const(0x15)
TMR_DN = const(0x7)

i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=10000)
fdd = FDD.FourDigitDisplay(i2c)
#i2c.scan()
fdd.clear()

ir_code_old = 0
ir_code_new = 0

speed = 0 # Hz
fan_on = False
swing_on = False
t0 = Timer(0)

def toogle_speed(t):
    speed_ctl.value(not speed_ctl.value())

def change_speed(speed):
    global t0
    global fdd
    if (speed):
        t0.init(freq=speed*2*50, mode=Timer.PERIODIC, callback=toogle_speed)
    else:
        t0.deinit()
    fdd.showbit(int(speed),3)

def beep():
    buzz.value(1)
    time.sleep_ms(100)
    buzz.value(0)
    
def ir_cb(data, addr, ctrl):
    global ir_code_new
    global ir_code_old
    global ADDR
    if data < 0:  # NEC protocol sends repeat codes.
        print('Repeat code.')
    else:
        print('Data {:02x} Addr {:04x}'.format(data, addr))
        if (addr == ADDR):
            ir_code_new = data
            ir_code_old = 0

ir = NEC_8(IR, ir_cb)


client = MQTTClient(
    #client_id="client_test_fan_sub",
    client_id=ubinascii.hexlify(machine.unique_id()),
    keepalive=60,
    server="test.mosquitto.org", 
    ssl=False)

client.connect(False) # robust 模組,這裡填 False

def get_msg(topic, msg):
    global ir_code_new
    global ir_code_old
    print("MQTT: ",msg)
    # 解析訊息,控制風扇
    # 以下借用 紅外線的控制碼來控制風扇,所以讓主流程都不需要更改!
    m = msg.decode("utf-8")
    if (m == 'power'):
        ir_code_new = PWR_ON
        ir_code_old = 0
    elif (m == 'swing'):
        ir_code_new = SWING
        ir_code_old = 0
    elif (m == 'up'):
        ir_code_new = SPD_UP
        ir_code_old = 0
    elif (m == 'down'):
        ir_code_new = SPD_DN
        ir_code_old = 0

client.set_callback(get_msg)
client.subscribe(b'Fan/Control')


# power on beep()
beep()
beep()
beep()
beep()

while True:
    time.sleep_ms(100)
    client.check_msg()
    if (ir_code_new == ir_code_old):
        continue
    print('Cheking...')
    beep()
    ir_code_old = ir_code_new
    if (ir_code_new == PWR_ON):
        if (fan_on == True):
            speed = 0
            fan_on = False
            swing_on = False
            swing.value(swing_on)
            change_speed(speed)
            fdd.clear()
            beep()
            time.sleep_ms(200)
            beep()
            print('Off')
        else:
            fan_on = True
            speed = 1
            change_speed(speed)
            print('On')
            continue
    
    if (fan_on == True):
        if (ir_code_new == SPD_UP): # increase speed
            speed += 1
            if (speed > 8): speed = 8
            change_speed(speed)
        elif (ir_code_new == SPD_DN): #decrease speed
            speed -= 1
            if (speed < 0): speed = 0
            change_speed(speed)
        elif (ir_code_new == SWING): #swing
            swing_on = not swing_on
            swing.value(swing_on)
            
    print('Done...')
            

上一篇
28. 使用MQTT
下一篇
30.結語
系列文
ESP32 Micropython 從入門到實用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言